/**
 * @file       EditField.cpp
 * @brief      TODO
 * @author     Huabo Zheng
 * @date       Jan 12, 2012
 * @Copyright  2012, www.netgear.com Inc. All rights reserved.
 */

#include "EditField.h"
#include "Char.h"
#include "errorcode.h"
#include "typedefine.h"
#include <iosfwd>
#include <sstream>
#include <algorithm>

namespace NS_LCD_AFW
{

CEditField::CEditField()
{
	this->setFocusable(true);
	this->setHightlightable(true);
	this->m_pageResult.setTotalPage(1);
	this->m_pageResult.setCurPage(1);
	this->m_pageResult.setDirection(CPageInfo::UNKNOW);
	m_charPtrArray.clear();
}

CEditField::~CEditField()
{
	release();
}

void CEditField::release()
{
	CFramePtrArray::iterator iter = m_charPtrArray.begin();
	for (; iter != m_charPtrArray.end(); ++iter)
	{
		//OBJ_DELETE((*iter));
		(*iter)->destory();
		(*iter) = NULL;
	}
	m_charPtrArray.clear();

}

int CEditField::setText(std::string text)
{
	release();
	int iRet = ERR_SUCCESS;
	std::ostringstream strName;
	CChar *pTmp = NULL;
	CRect rect(0, 0, 1, 1);
	for (std::size_t i = 0; i < text.length(); ++i)
	{
		OBJ_NEW(CChar, pTmp);
		if (NULL == pTmp)
		{
			return ERR_NO_MEMORY;
		}
		strName << "CChar" << i;
		iRet = pTmp->create(strName.str(), rect, this);
		if (iRet != ERR_SUCCESS)
		{
			pTmp->destory();
			pTmp = NULL;
			return iRet;
		}
		pTmp->setChar(text[i]);
		m_charPtrArray.push_back(pTmp);
	}

	iRet = m_pageingStrategy.calculatePaging(this->m_charPtrArray,
			this->getRect(), this->m_pageResult);
	if (iRet != ERR_SUCCESS)
	{
		return iRet;
	}
	m_pageResult.setDirection(CPageInfo::UNKNOW);
	this->m_pageResult.setCurPage(1);
	m_pageingStrategy.calculateViewPort(m_charPtrArray, this->getRect(),
			m_pageResult);
	return ERR_SUCCESS;
}

std::string CEditField::getText() const
{
	std::string strRet = "";
	CFramePtrArray::const_iterator iter = this->m_charPtrArray.begin();
	for (; iter != this->m_charPtrArray.end(); ++iter)
	{
		strRet += ((CChar*) (((*iter))))->getChar();
	}
	return strRet;
}

int CEditField::onDraw(IDisplay *pDisplay)
{
	if (NULL == pDisplay)
	{
		return ERR_NULL_POINTER;
	}
	if (!this->isVisible())
	{
		return ERR_OBJECT_UN_VISIBLE;
	}

	CRect thisRect = this->getRect();
	CPoint thisPostion = getPosition();

	if (m_pageResult.isNeedSwitchPage())
	{
		pDisplay->cleanScreen(thisPostion.getX(), thisPostion.getY(),
				thisRect.getWidth(), thisRect.getHight());
		int offsetX = 0;
		int offsetY = 0;
		for (int i = m_pageResult.getStartIndex();
				i < m_pageResult.getEndIndex() && i < (int)m_charPtrArray.size(); ++i)
		{
			CPoint pt(thisPostion.getX() + offsetX,
					thisPostion.getY() + offsetY);
			m_charPtrArray[i]->setPosition(pt);
			m_charPtrArray[i]->onDraw(pDisplay);
			if (offsetX >= thisRect.getWidth() && offsetX % thisRect.getWidth() == 0)
			{
				offsetX = 0;
				offsetY++;
			}
			else
			{
				offsetX++;
			}
		}

	}

	return CFrame::onDraw(pDisplay);
}

void CEditField::onSetFocus()
{
	if (this->isHightlight())
	{
		this->onEnterKeyPress();
		//this->setHightlight(false);
	}


}

void CEditField::onLostFocus()
{
}

void CEditField::onHightlight()
{

}

void CEditField::onUnHightlight()
{
}

int CEditField::onRightKeyPress()
{
	return this->onEnterKeyPress();
}

int CEditField::onLeftKeyPress()
{
	return this->onEscKeyPress();
}

int CEditField::onUpKeyPress()
{
	if (this->isHightlight())
	{
		this->m_pageResult.setDirection(CPageInfo::UP);
		if (ERR_NO_CHANGE
				== m_pageingStrategy.calculateViewPort(m_charPtrArray,
						this->getRect(), m_pageResult))
		{
			//Has come to the first page, can not page up so took the message to the parent window handle
			this->setFocus(false);
			this->setHightlight(false);
			//maKe the parent frame happy
			return ERR_EVENT_UN_HANDLED;
		}
		else
		{
			this->invalidate();
			return ERR_SUCCESS;
		}
	}
	else
	{
		//TODO:Switching line upward
		return CFrame::onUpKeyPress();
	}
}

int CEditField::onDownKeyPress()
{
	if (this->isHightlight())
	{
		this->m_pageResult.setDirection(CPageInfo::DOWN);
		if (ERR_NO_CHANGE
				== m_pageingStrategy.calculateViewPort(m_charPtrArray,
						this->getRect(), m_pageResult))
		{
			//Has reached the final page, can not scroll down, so took the message to the parent window handle
			this->setFocus(false);
			this->setHightlight(false);
			//maKe the parent frame happy
			return ERR_EVENT_UN_HANDLED;
		}
		else
		{
			this->invalidate();
			return ERR_SUCCESS;
		}
	}
	else
	{
		//TODO: Switching line downward
		return CFrame::onUpKeyPress();
	}
}

int CEditField::onEnterKeyPress()
{
	if (this->isHightlight())
	{
		this->m_pageResult.setDirection(CPageInfo::UNKNOW);
		if (ERR_NO_CHANGE
				== m_pageingStrategy.calculateViewPort(m_charPtrArray,
						this->getRect(), m_pageResult))
		{
//			this->setFocus(false);
//			this->setHightlight(false);
			//maKe the parent frame happy
			return ERR_EVENT_UN_HANDLED;
		}
		else
		{
			//change to the editor mode,and set the focus to the first char;
			this->setHightlight(false);
			//this->invalidate();
			if ((int)m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
			{
				this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setHightlight(
						true);
				this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setFocus(
						true);
			}
			return ERR_SUCCESS;
		}
	}
	else
	{
		this->m_pageResult.setDirection(CPageInfo::RIGHT);
		if ((int)m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
		{
			this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setHightlight(
					false);
		}
		if (ERR_NO_CHANGE
				== m_pageingStrategy.calculateViewPort(m_charPtrArray,
						this->getRect(), m_pageResult)
				&& !m_pageResult.isValidHightLightObjIndex())
		{
			//Has reached the final character, can no longer move after, so highlight myself ,
			//and to deal with the message by my own;
			this->setFocus(true);
			this->setHightlight(true);
			return ERR_SUCCESS;
		}
		else
		{
			this->invalidate();
			if ((int)m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
			{
				this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setFocus(
						true);
			}
		}

		if ((int)m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
		{
			this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setHightlight(
					true);
		}
		return ERR_SUCCESS;
	}
}

int CEditField::addChar(CChar *pChar)
{
	if (NULL == pChar)
	{
		return ERR_NULL_POINTER;
	}
	CFramePtrArray::iterator iter = std::find(m_charPtrArray.begin(),
			m_charPtrArray.end(), pChar);
	if (iter != m_charPtrArray.end())
	{
		return ERR_ELEMENT_EXISTS;
	}
	m_charPtrArray.push_back(pChar);

	m_pageingStrategy.calculatePaging(this->m_charPtrArray, this->getRect(),
			this->m_pageResult);
	m_pageResult.setDirection(CPageInfo::UNKNOW);
	m_pageingStrategy.calculateViewPort(m_charPtrArray, this->getRect(),
			m_pageResult);
	return ERR_SUCCESS;
}

int CEditField::onEscKeyPress()
{
	if (this->isHightlight())
	{
		return ERR_EVENT_UN_HANDLED;
	}
	else
	{
		this->m_pageResult.setDirection(CPageInfo::LEFT);
		if (m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
		{
			this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setHightlight(
					false);
		}
		if (ERR_NO_CHANGE
				== m_pageingStrategy.calculateViewPort(m_charPtrArray,
						this->getRect(), m_pageResult)
				&& !m_pageResult.isValidHightLightObjIndex())
		{
			//Has reached the final character, can no longer move after, so highlight myself ,
			//and to deal with the message by my own;
			this->setFocus(true);
			this->setHightlight(true);
			return ERR_SUCCESS;
		}
		else
		{
			this->invalidate();
			if (m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
			{
				this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setFocus(
						true);
			}
		}
		if (m_charPtrArray.size() > m_pageResult.getHightLightObjIndex())
		{
			this->m_charPtrArray[m_pageResult.getHightLightObjIndex()]->setHightlight(
					true);
		}
		return ERR_SUCCESS;
	}
}
void CEditField::onSize(const CRect & oldRect, const CRect & newRect)
{
	if (newRect.isValidRect() && oldRect != newRect)
	{
		m_pageingStrategy.calculatePaging(this->m_charPtrArray, newRect,
				this->m_pageResult);
		m_pageResult.setDirection(CPageInfo::UNKNOW);
		m_pageingStrategy.calculateViewPort(m_charPtrArray, this->getRect(),
				m_pageResult);
	}
}

} /* namespace NS_LCD_AFW */
